#pragma once
#include "abstract.hpp"
namespace rpc
{
    class JsonMessage : public BaseMessage
    {
    public:
        virtual std::string serialize() override
        {
            std::string st;
            if (JsonUnit::serialize(_val, st))
            {
                return st;
            }
            return std::string();
        };
        virtual bool unserialize(const std::string &msg) override
        {
            return JsonUnit::unserialize(msg, _val);
        };

    protected:
        Json::Value _val;
    };
    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
    };
    class JsonResponse : public JsonMessage
    {
    public:
        virtual bool check() override
        {
            // 大部分的相应都只有相应状态码，只需判断字段是否存在，类型是否正确
            if (_val[KEY_RCODE].isNull())
            {
                ELOG("响应中没没有响应状态码");
                return false;
            }
            if (_val[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码错误");
                return false;
            }
            return true;
        }
        RCode rcode()
        {
            return (RCode)_val[KEY_RCODE].asInt();
        }
        void setRcode(const RCode &code)
        {
            _val[KEY_RCODE] = (int)code;
        }
    };
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            // 大部分的相应都只有相应状态码，只需判断字段是否存在，类型是否正确
            if (_val[KEY_METHOD].isNull() || _val[KEY_METHOD].isString() == false)
            {
                ELOG("rpc请求中没有方法名称或者方法名称错误");
                return false;
            }
            if (_val[KEY_PARA].isNull() || _val[KEY_PARA].isObject() == false)
            {
                ELOG("rpc请求中没有参数信息或者参数信息错误");
                return false;
            }
            return true;
        }
        std::string Method()
        {
            return _val[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method)
        {
            _val[KEY_METHOD] = method;
        }
        Json::Value Para()
        {
            return _val[KEY_PARA];
        }
        void setPara(const Json::Value &para)
        {
            _val[KEY_PARA] = para;
        }
    };
    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            // 大部分的相应都只有相应状态码，只需判断字段是否存在，类型是否正确
            if (_val[KEY_TOPIC_KEY].isNull() || _val[KEY_TOPIC_KEY].isString() == false)
            {
                ELOG("主题请求中没有方法名称或者方法名称错误");
                return false;
            }
            if (_val[KEY_OPTYPE].isNull() || _val[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("主题请求中没有操作类型或者操作类型错误");
                return false;
            }
            return true;
            if (_val[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH &&
                (_val[KEY_TOPIC_MSG].isNull() ||
                 _val[KEY_TOPIC_MSG].isIntegral() == false))
            {
                ELOG("主题消息发布请求中没有消息或者消息类型错误");
                return false;
            }
            return true;
        }
        std::string TopicKey()
        {
            return _val[KEY_TOPIC_KEY].asString();
        }
        void setTopicKey(const std::string &topickey)
        {
            _val[KEY_TOPIC_KEY] = topickey;
        }
        TopicOptype Topicoptype()
        {
            return (TopicOptype)_val[KEY_OPTYPE].asInt();
        }
        void setTopicoptype(const TopicOptype &topicoptype)
        {
            _val[KEY_OPTYPE] = (int)topicoptype;
        }
        std::string TopicMsg()
        {
            return _val[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const std::string &topicmsg)
        {
            _val[KEY_TOPIC_MSG] = topicmsg;
        }
    };
    typedef std::pair<std::string, int> Address;
    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            // 大部分的相应都只有相应状态码，只需判断字段是否存在，类型是否正确
            if (_val[KEY_METHOD].isNull() || _val[KEY_METHOD].isString() == false)
            {
                ELOG("服务请求中没有方法名称或者方法名称错误");
                return false;
            }
            if (_val[KEY_OPTYPE].isNull() || _val[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("服务请求中没有操作类型或者操作类型错误");
                return false;
            }
            return true;
            if (_val[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVER) &&
                    _val[KEY_HOST].isNull() ||
                _val[KEY_HOST].isObject() == false ||
                _val[KEY_HOST_IP].isNull() ||
                _val[KEY_HOST_IP].isString() == false ||
                _val[KEY_HOST_PORT].isNull() ||
                _val[KEY_HOST_PORT].isIntegral() == false)
            {
                ELOG("服务请求中地址信息错误");
                return false;
            }
            return true;
        }
        std::string Method()
        {
            return _val[KEY_METHOD].asString();
        }
        void setMethod(const std::string &topickey)
        {
            _val[KEY_METHOD] = topickey;
        }
        ServiceOptype Serviceoptype()
        {
            return (ServiceOptype)_val[KEY_OPTYPE].asInt();
        }
        void setServiceoptype(const ServiceOptype &topicoptype)
        {
            _val[KEY_OPTYPE] = (int)topicoptype;
        }
        Address Host()
        {
            Address arr;
            arr.first = _val[KEY_HOST][KEY_HOST_IP].asString();
            arr.second = _val[KEY_HOST][KEY_HOST_PORT].asInt();
            return arr;
        }
        void setHost(const Address &arr)
        {
            Json::Value val;
            val[KEY_HOST_IP] = arr.first;
            val[KEY_HOST_PORT] = arr.second;
            _val[KEY_HOST] = val;
        }
    };
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            if (_val[KEY_RCODE].isNull())
            {
                ELOG("响应中没没有响应状态码");
                return false;
            }
            if (_val[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码错误");
                return false;
            }
            if (_val[KEY_RESULT].isNull() || _val[KEY_RESULT].isObject() == false)
            {
                ELOG("响应中没有结果或者结果错误");
                return false;
            }
            return true;
        }
        /*RCode rcode()
        {
            return (RCode)_val[KEY_RCODE].asInt();
        }
        void SetRcode(RCode& code)
        {
            _val[KEY_RCODE]=(int)code;
        }*/
        Json::Value Result()
        {
            return _val[KEY_RESULT];
        }
        void setResult(Json::Value result)
        {
            _val[KEY_RESULT] = result;
        }
    };
    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        /*RCode rcode()
        {
            return (RCode)_val[KEY_RCODE].asInt();
        }
        void SetRcode(RCode& code)
        {
            _val[KEY_RCODE]=(int)code;
        }*/
    };
    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            if (_val[KEY_RCODE].isNull())
            {
                ELOG("响应中没没有响应状态码");
                return false;
            }
            if (_val[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码错误");
                return false;
            }
            if (_val[KEY_OPTYPE].isNull() || _val[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("响应中没有操作类型或者操作类型错误");
                return false;
            }
            if (_val[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVER) &&
                (_val[KEY_METHOD].isNull() ||
                 _val[KEY_METHOD].isString() == false ||
                 _val[KEY_HOST].isNull() ||
                 _val[KEY_HOST].isArray() == false))
            {
                ELOG("服务发现响应中响应信息字段错误");
                return false;
            }
            return true;
        }
        /*RCode rcode()
        {
           return  (RCode)_val[KEY_RCODE].asInt();
        }
        void SetRcode(RCode& code)
        {
            _val[KEY_RCODE]=(int)code;
        }*/
        std::string Method()
        {
            return _val[KEY_METHOD].asString();
        }
        void setMethod(std::string result)
        {
            _val[KEY_METHOD] = result;
        }
        void setHost(std::vector<Address> &arr)
        {
            for (auto &add : arr)
            {
                Json::Value val;
                val[KEY_HOST_IP] = add.first;
                val[KEY_HOST_PORT] = add.second;
                _val[KEY_HOST].append(val);
            }
        }
        void setOptype(const ServiceOptype&optype)
        {
            _val[KEY_OPTYPE]=(int)optype;
        }
        std::vector<Address> Host()
        {
            std::vector<Address> add;
            int sz = _val[KEY_HOST].size();
            for (int i = 0; i < sz; i++)
            {
                Address addr;
                addr.first = _val[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _val[KEY_HOST][i][KEY_HOST_PORT].asInt();
                add.push_back(addr);
            }
            return add;
        }
    };
    // 实现一个消息对象的生产工厂
    class MessageFactory
    {
    public:
        static BaseMessage::ptr create(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
            }
            return BaseMessage::ptr();
        }
        template <typename T, typename... Args>
        static std::shared_ptr<T> create(Args &&...args)
        {
            return std::make_shared<T>(std::forward(args)...);
        }
    };

}